package com.example.test3ddemo

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.content.Context
import android.util.Log
import android.widget.Button
import android.widget.Toast
import com.google.android.filament.Material
import io.github.sceneview.SceneView
import io.github.sceneview.math.Position
import io.github.sceneview.math.Rotation
import io.github.sceneview.math.Scale
import io.github.sceneview.node.ModelNode
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.IOException
import java.nio.ByteBuffer
import com.google.android.filament.MaterialInstance as FilamentMaterialInstance

class Two_Activity : AppCompatActivity() {
    private lateinit var sceneView: SceneView
    private var isSceneViewInitialized = false
    private var currentModelNode: ModelNode? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_two)

        sceneView = findViewById(R.id.sceneView)

        setupScene()
        setupUI()
    }

    /**
     * **初始化3D模型**
     */
    private fun setupScene() {
        try {
            CoroutineScope(Dispatchers.Main).launch {
                try {
                    val glbData = loadGLBFromAssets(this@Two_Activity, "models/Terra_3D_demo.gltf") ?: return@launch
                    val modelInstance = sceneView.modelLoader.createModelInstance(glbData)
                    if (modelInstance != null) {
                        val modelNode = ModelNode(modelInstance).apply {
                            position = Position(0.0f, 0.0f, -5.0f)
                            scale = Scale(1.0f)
                            rotation = Rotation(0.0f, 0.0f, 0.0f)
                        }
                        currentModelNode = modelNode
                        sceneView.addChildNode(modelNode)
                        sceneView.invalidate()
                        Toast.makeText(this@Two_Activity, "模型加载成功", Toast.LENGTH_SHORT).show()
                    } else {
                        Toast.makeText(this@Two_Activity, "模型加载失败：返回为空", Toast.LENGTH_LONG).show()
                    }
                } catch (e: Exception) {
                    Log.e("MainActivity", "Error loading model: ${e.localizedMessage}", e)
                }
            }
        } catch (e: Exception) {
            Log.e("MainActivity", "Error in setupScene", e)
        }
    }

    /**
     * **创建玻璃材质**
     */
    private fun createGlassMaterial(): FilamentMaterialInstance? {
        return loadMaterialFromAsset("materials/terra_bl.filamat")?.apply {
            setParameter("baseColor", 0.8f, 0.9f, 1.0f, 0.3f)
            setParameter("metallic", 0.0f)
            setParameter("roughness", 0.1f)
            setParameter("reflectance", 0.9f)
        }
    }

    /**
     * **创建金属材质**
     */
    private fun createMetalMaterial(): FilamentMaterialInstance? {
        return loadMaterialFromAsset("materials/terra_bl.filamat")?.apply {
            setParameter("baseColor", 0.75f, 0.75f, 0.75f, 1.0f)
            setParameter("metallic", 1.0f)
            setParameter("roughness", 0.2f)
        }
    }

    /**
     * **创建硅胶材质**
     */
    private fun createSiliconeMaterial(): FilamentMaterialInstance? {
        return loadMaterialFromAsset("materials/terra_ys.filamat")?.apply {
            setParameter("baseColor", 0.95f, 0.7f, 0.75f, 1.0f)
            setParameter("metallic", 0.0f)
            setParameter("roughness", 0.3f)
            setParameter("opacity", 0.8f)
        }
    }

    /**
     * **加载 .filamat 材质**
     */
    private fun loadMaterialFromAsset(filePath: String): FilamentMaterialInstance? {
        return try {
            val inputStream = this.assets.open(filePath)
            val byteArray = inputStream.readBytes()
            inputStream.close()
            val buffer = ByteBuffer.wrap(byteArray)

            val material = Material.Builder()
                .payload(buffer, byteArray.size)
                .build(sceneView.engine)

            Log.d("MainActivity", "材质加载成功: $filePath")
            material.createInstance()
        } catch (e: Exception) {
            Log.e("MainActivity", "材质加载失败: ${e.localizedMessage}")
            null
        }
    }

    /**
     * **切换材质**
     */
    private fun applyMaterialToAllNodes(newMaterial: FilamentMaterialInstance?) {
        currentModelNode?.model?.let { model ->
            model.instance?.let { instance ->
                if (newMaterial == null) {
                    Log.e("MainActivity", "新材质为空")
                    return
                }

                // ✅ **确保所有网格都应用材质**
                for (i in instance.materialInstances.indices) {
                    instance.materialInstances[i] = newMaterial
                }

                // ✅ **强制刷新 SceneView**
                sceneView.invalidate()


                Log.d("MainActivity", "成功应用新材质")
            }
        }
    }

    /**
     * **恢复默认材质**
     */
    private fun restoreOriginalMaterials() {
        currentModelNode?.model?.instance?.let { instance ->
            for (i in instance.materialInstances.indices) {
                instance.materialInstances[i] = instance.materialInstances[i]
            }
        }
        sceneView.invalidate()
    }

    /**
     * **UI 按钮事件**
     */
    private fun setupUI() {
        findViewById<Button>(R.id.btnGlass).setOnClickListener {
            applyMaterialToAllNodes(createGlassMaterial())
        }

        findViewById<Button>(R.id.btnSilicone).setOnClickListener {
            applyMaterialToAllNodes(createSiliconeMaterial())
        }

        findViewById<Button>(R.id.btnMetal).setOnClickListener {
            applyMaterialToAllNodes(createMetalMaterial())
        }

        findViewById<Button>(R.id.btnOriginal).setOnClickListener {
            restoreOriginalMaterials()
        }
    }

    fun loadGLBFromAssets(context: Context, filePath: String): ByteBuffer? {
        return try {
            val inputStream = context.assets.open(filePath)
            val bytes = inputStream.readBytes()
            inputStream.close()
            ByteBuffer.wrap(bytes)
        } catch (e: IOException) {
            Log.e("MainActivity", "模型加载失败: ${e.localizedMessage}")
            null
        }
    }
}
